#ifndef RENDERER_H
#define RENDERER_H
#include "ProjectHeader.h"
#include "Camera.h"	
#include "UIElement-Slider.h"	//TEST

struct DrawerDelegateStorageType	//NOTE: This is here, rather than in ProjectHeader, because it's strictly internal to Renderer
{
	DrawEvent_delegate Drawer;
	Transform_delegate Transformer;
	enum DRAW_TYPE GlHint;
	DrawerDelegateStorageType()
	{
		Drawer = NULL;
		Transformer = NULL;
		GlHint = STATIC;
	}
};

struct DrawerDelegateDrawingType	//NOTE: This is here, rather than in ProjectHeader, because it's strictly internal to Renderer
{
	Transform_delegate Transformer;
	GLuint VBO;
	GLuint ElementCount;
	DrawerDelegateDrawingType()
	{
		Transformer = NULL;
		VBO = 0;
		ElementCount = 0;
	}
};

class Renderer
{
private:

	std::vector<DrawerDelegateStorageType>					VBODelegateStore;
	std::map<int, std::vector<DrawerDelegateDrawingType>>	VBODrawingStore;
	std::vector<DrawerDelegateStorageType>					OverlayDelegateStore;
	std::map<int, std::vector<DrawerDelegateDrawingType>>	OverlayDrawingStore;

	UISliderElement TestUIElement;		//TEST
	Camera sceneCamera;
	vertex2f screenSize;

	GLfloat LightAmbient[4];	// Ambient light
	GLfloat LightDiffuse[4];	// Diffuse light
	GLfloat LightPosition[4];	// Light Position
	bool light;					// set lighting effects on/off
	bool blend;					// set blending effects on/off
	bool redrawStatics;			// If true, statics are redrawn next frame.

	int LoadTexture(const char *File);	//Load a texture using soil; adds it to Texture[] and returns the index.

	void MakeDrawStore(const std::vector<DrawerDelegateStorageType> &DDSTvec, std::map<int, std::vector<DrawerDelegateDrawingType>> &DDDTmap);
	void MakeVBODrawStore();	//Builds the VBODrawStore from DrawDelegates.
	void MakeOverlayDrawStore();//Builds the OverlayDrawingStore from DrawDelegates.

	void SizeDrawStore(const std::vector<DrawerDelegateStorageType> &DDSTVec, std::map<int, std::vector<DrawerDelegateDrawingType>> &DDDTmap);	//ensures that there are enough space

	void DrawVBODrawStore();	//Draws VBOs to screen
	void DrawOverlayStore();	//Draws the UI over the screen.

	void ApplyTransform(const Transform &t);
	void DrawDDDT(std::map<int, Transform> &TransformCache, int DrawerNum, const DrawerDelegateDrawingType &DDDT);

	GLuint HUDVBO;

	GLuint CurrentBoundTex;	//Stores OGL pointer of the currently bound texture; saves an OGL call by preventing unneccecary changes.
	std::map<int, texCoord2f> TexCoords;	//maps internal texture coords to coordinates in a texAtlas; The atlas's index in Texture is also stored.

	std::vector<GLuint> Texture;	//Stores OGL pointers to Texture Atlases
	std::vector<DrawEvent_delegate> HUDDrawList;	//Holds HUD Drawing fastDelegates.
	std::vector<std::vector<std::vector<GLsizei>>> elementCount;	//Stores the number of vertexes in the VBO from a draw method

public:

	GLfloat xView;
	GLfloat depth;

	int TestStatFunc(int i);	//TEST

	Renderer();				// Constructor

	int InitGL();

	void ReSizeGLScene(GLsizei width, GLsizei height);	//Resizes the scene
	void ReSizeGLScene(UINT msg, WPARAM wParam, LPARAM lParam);	// Overload; Called through a fastDelegate. Reads the message and resizes to the new window size.

	bool RegisterDraw(DrawEventPair, enum DRAW_TYPE);			// Registers delegates to produce geometry, and apply transforms at draw time. 
	bool RegisterDraw(DrawEvent_delegate, enum DRAW_TYPE);		// Overload; Registers a delegate to be called when drawing, without transforms.

	bool RegisterUIDraw(DrawEvent_delegate, enum DRAW_TYPE);
	bool RegisterUIDraw(DrawEventPair, enum DRAW_TYPE);

	int DrawGLScene();		//Draws the scene; will update VBOs and call any relevent transform delegates too.

	GLvoid toggleLight();		//Turn lighting effects on/off
	GLvoid toggleBlend();		//Turn blending effects on/off

	const std::map<int, texCoord2f>& getTexCoords();	//Returns a const reference to the texture map

};
#endif